home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / demo2.zoo / demo / ex / ex_vops3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-24  |  9.7 KB  |  558 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *sccsid = "@(#)ex_vops3.c    7.4 (Berkeley) 3/9/87; 1.2 (Bellcore)    87/04/24";
  9. #endif not lint
  10.  
  11. #include "ex.h"
  12. #include "ex_tty.h"
  13. #include "ex_vis.h"
  14.  
  15. /*
  16.  * Routines to handle structure.
  17.  * Operations supported are:
  18.  *    ( ) { } [ ]
  19.  *
  20.  * These cover:        LISP        TEXT
  21.  *    ( )        s-exprs        sentences
  22.  *    { }        list at same    paragraphs
  23.  *    [ ]        defuns        sections
  24.  *
  25.  * { and } for C used to attempt to do something with matching {}'s, but
  26.  * I couldn't find definitions which worked intuitively very well, so I
  27.  * scrapped this.
  28.  *
  29.  * The code here is very hard to understand.
  30.  */
  31. line    *llimit;
  32. int    (*lf)();
  33.  
  34. #ifdef LISPCODE
  35. int    lindent();
  36. #endif
  37.  
  38. bool    wasend;
  39.  
  40. /*
  41.  * Find over structure, repeated count times.
  42.  * Don't go past line limit.  F is the operation to
  43.  * be performed eventually.  If pastatom then the user said {}
  44.  * rather than (), implying past atoms in a list (or a paragraph
  45.  * rather than a sentence.
  46.  */
  47. lfind(pastatom, cnt, f, limit)
  48.     bool pastatom;
  49.     int cnt, (*f)();
  50.     line *limit;
  51. {
  52.     register int c;
  53.     register int rc = 0;
  54.     char save[LBSIZE];
  55.  
  56.     /*
  57.      * Initialize, saving the current line buffer state
  58.      * and computing the limit; a 0 argument means
  59.      * directional end of file.
  60.      */
  61.     wasend = 0;
  62.     lf = f;
  63.     strcpy(save, linebuf);
  64.     if (limit == 0)
  65.         limit = dir < 0 ? one : dol;
  66.     llimit = limit;
  67.     wdot = dot;
  68.     wcursor = cursor;
  69.  
  70.     if (pastatom >= 2) {
  71.         while (cnt > 0 && word(f, cnt))
  72.             cnt--;
  73.         if (pastatom == 3)
  74.             eend(f);
  75.         if (dot == wdot) {
  76.             wdot = 0;
  77.             if (cursor == wcursor)
  78.                 rc = -1;
  79.         }
  80.     }
  81. #ifdef LISPCODE
  82.     else if (!value(LISP)) {
  83. #else
  84.     else {
  85. #endif
  86.         char *icurs;
  87.         line *idot;
  88.  
  89.         if (linebuf[0] == 0) {
  90.             do
  91.                 if (!lnext())
  92.                     goto ret;
  93.             while (linebuf[0] == 0);
  94.             if (dir > 0) {
  95.                 wdot--;
  96.                 linebuf[0] = 0;
  97.                 wcursor = linebuf;
  98.                 /*
  99.                  * If looking for sentence, next line
  100.                  * starts one.
  101.                  */
  102.                 if (!pastatom) {
  103.                     icurs = wcursor;
  104.                     idot = wdot;
  105.                     goto begin;
  106.                 }
  107.             }
  108.         }
  109.         icurs = wcursor;
  110.         idot = wdot;
  111.  
  112.         /*
  113.          * Advance so as to not find same thing again.
  114.          */
  115.         if (dir > 0) {
  116.             if (!lnext()) {
  117.                 rc = -1;
  118.                 goto ret;
  119.             }
  120.         } else
  121.             ignore(lskipa1(""));
  122.  
  123.         /*
  124.          * Count times find end of sentence/paragraph.
  125.          */
  126. begin:
  127.         for (;;) {
  128.             while (!endsent(pastatom))
  129.                 if (!lnext())
  130.                     goto ret;
  131.             if (!pastatom || wcursor == linebuf && endPS())
  132.                 if (--cnt <= 0)
  133.                     break;
  134.             if (linebuf[0] == 0) {
  135.                 do
  136.                     if (!lnext())
  137.                         goto ret;
  138.                 while (linebuf[0] == 0);
  139.             } else
  140.                 if (!lnext())
  141.                     goto ret;
  142.         }
  143.  
  144.         /*
  145.          * If going backwards, and didn't hit the end of the buffer,
  146.          * then reverse direction.
  147.          */
  148.         if (dir < 0 && (wdot != llimit || wcursor != linebuf)) {
  149.             dir = 1;
  150.             llimit = dot;
  151.             /*
  152.              * Empty line needs special treatement.
  153.              * If moved to it from other than begining of next line,
  154.              * then a sentence starts on next line.
  155.              */
  156.             if (linebuf[0] == 0 && !pastatom && 
  157.                (wdot != dot - 1 || cursor != linebuf)) {
  158.                 ignore(lnext());
  159.                 goto ret;
  160.             }
  161.         }
  162.  
  163.         /*
  164.          * If we are not at a section/paragraph division,
  165.          * advance to next.
  166.          */
  167.         if (wcursor == icurs && wdot == idot || wcursor != linebuf || !endPS())
  168.             ignore(lskipa1(""));
  169.     }
  170. #ifdef LISPCODE
  171.     else {
  172.         c = *wcursor;
  173.         /*
  174.          * Startup by skipping if at a ( going left or a ) going
  175.          * right to keep from getting stuck immediately.
  176.          */
  177.         if (dir < 0 && c == '(' || dir > 0 && c == ')') {
  178.             if (!lnext()) {
  179.                 rc = -1;
  180.                 goto ret;
  181.             }
  182.         }
  183.         /*
  184.          * Now chew up repitition count.  Each time around
  185.          * if at the beginning of an s-exp (going forwards)
  186.          * or the end of an s-exp (going backwards)
  187.          * skip the s-exp.  If not at beg/end resp, then stop
  188.          * if we hit a higher level paren, else skip an atom,
  189.          * counting it unless pastatom.
  190.          */
  191.         while (cnt > 0) {
  192.             c = *wcursor;
  193.             if (dir < 0 && c == ')' || dir > 0 && c == '(') {
  194.                 if (!lskipbal("()"))
  195.                     goto ret;
  196.                 /*
  197.                   * Unless this is the last time going
  198.                  * backwards, skip past the matching paren
  199.                  * so we don't think it is a higher level paren.
  200.                  */
  201.                 if (dir < 0 && cnt == 1)
  202.                     goto ret;
  203.                 if (!lnext() || !ltosolid())
  204.                     goto ret;
  205.                 --cnt;
  206.             } else if (dir < 0 && c == '(' || dir > 0 && c == ')')
  207.                 /* Found a higher level paren */
  208.                 goto ret;
  209.             else {
  210.                 if (!lskipatom())
  211.                     goto ret;
  212.                 if (!pastatom)
  213.                     --cnt;
  214.             }
  215.         }
  216.     }
  217. #endif
  218. ret:
  219.     strcLIN(save);
  220.     return (rc);
  221. }
  222.  
  223. /*
  224.  * Is this the end of a sentence?
  225.  */
  226. /* ARGSUSED */
  227. endsent(pastatom)
  228.     bool pastatom;
  229. {
  230.     register char *cp = wcursor;
  231.     register int d;
  232.  
  233.     /*
  234.      * If this is the beginning of a line, then
  235.      * check for the end of a paragraph or section.
  236.      */
  237.     if (cp == linebuf)
  238.         return (endPS());
  239.  
  240.     /*
  241.      * Sentences end with . ! ? not at the beginning
  242.      * of the line, and must be either at the end of the line,
  243.      * or followed by 2 spaces.  Any number of intervening ) ] ' "
  244.      * characters are allowed.
  245.      */
  246.     if (!any(*cp, ".!?"))
  247.         goto tryps;
  248.     do
  249.         if ((d = *++cp) == 0)
  250.             return (1);
  251.     while (any(d, ")]'"));
  252.     if (*cp == 0 || *cp++ == ' ' && *cp == ' ')
  253.         return (1);
  254. tryps:
  255.     if (cp[1] == 0)
  256.         return (endPS());
  257.     return (0);
  258. }
  259.  
  260. /*
  261.  * End of paragraphs/sections are respective
  262.  * macros as well as blank lines and form feeds.
  263.  */
  264. endPS()
  265. {
  266.  
  267.     return (linebuf[0] == 0 ||
  268.         isa(svalue(PARAGRAPHS)) || isa(svalue(SECTIONS)));
  269.         
  270. }
  271.  
  272. #ifdef LISPCODE
  273. lindent(addr)
  274.     line *addr;
  275. {
  276.     register int i;
  277.     char *swcurs = wcursor;
  278.     line *swdot = wdot;
  279.  
  280. again:
  281.     if (addr > one) {
  282.         register char *cp;
  283.         register int cnt = 0;
  284.  
  285.         addr--;
  286.         getline(*addr);
  287.         for (cp = linebuf; *cp; cp++)
  288.             if (*cp == '(')
  289.                 cnt++;
  290.             else if (*cp == ')')
  291.                 cnt--;
  292.         cp = vpastwh(linebuf);
  293.         if (*cp == 0)
  294.             goto again;
  295.         if (cnt == 0)
  296.             return (whitecnt(linebuf));
  297.         addr++;
  298.     }
  299.     wcursor = linebuf;
  300.     linebuf[0] = 0;
  301.     wdot = addr;
  302.     dir = -1;
  303.     llimit = one;
  304.     lf = lindent;
  305.     if (!lskipbal("()"))
  306.         i = 0;
  307.     else if (wcursor == linebuf)
  308.         i = 2;
  309.     else {
  310.         register char *wp = wcursor;
  311.  
  312.         dir = 1;
  313.         llimit = wdot;
  314.         if (!lnext() || !ltosolid() || !lskipatom()) {
  315.             wcursor = wp;
  316.             i = 1;
  317.         } else
  318.             i = 0;
  319.         i += column(wcursor) - 1;
  320.         if (!inopen)
  321.             i--;
  322.     }
  323.     wdot = swdot;
  324.     wcursor = swcurs;
  325.     return (i);
  326. }
  327. #endif
  328.  
  329. lmatchp(addr)
  330.     line *addr;
  331. {
  332.     register int i;
  333.     register char *parens, *cp;
  334.  
  335.     for (cp = cursor; !any(*cp, "({[)}]");)
  336.         if (*cp++ == 0)
  337.             return (0);
  338.     lf = 0;
  339.     parens = any(*cp, "()") ? "()" : any(*cp, "[]") ? "[]" : "{}";
  340.     if (*cp == parens[1]) {
  341.         dir = -1;
  342.         llimit = one;
  343.     } else {
  344.         dir = 1;
  345.         llimit = dol;
  346.     }
  347.     if (addr)
  348.         llimit = addr;
  349.     if (splitw)
  350.         llimit = dot;
  351.     wcursor = cp;
  352.     wdot = dot;
  353.     i = lskipbal(parens);
  354.     return (i);
  355. }
  356.  
  357. lsmatch(cp)
  358.     char *cp;
  359. {
  360.     char save[LBSIZE];
  361.     register char *sp = save;
  362.     register char *scurs = cursor;
  363.  
  364.     wcursor = cp;
  365.     strcpy(sp, linebuf);
  366.     *wcursor = 0;
  367.     strcpy(cursor, genbuf);
  368.     cursor = strend(linebuf) - 1;
  369.     if (lmatchp(dot - vcline)) {
  370.         register int i = insmode;
  371.         register int c = outcol;
  372.         register int l = outline;
  373.  
  374.         if (!MI)
  375.             endim();
  376.         vgoto(splitw ? WECHO : LINE(wdot - llimit), column(wcursor) - 1);
  377.         flush();
  378.         sleep(1);
  379.         vgoto(l, c);
  380.         if (i)
  381.             goim();
  382.     }
  383.     else {
  384.         strcLIN(sp);
  385.         strcpy(scurs, genbuf);
  386.         if (!lmatchp((line *) 0))
  387.             beep();
  388.     }
  389.     strcLIN(sp);
  390.     wdot = 0;
  391.     wcursor = 0;
  392.     cursor = scurs;
  393. }
  394.  
  395. ltosolid()
  396. {
  397.  
  398.     return (ltosol1("()"));
  399. }
  400.  
  401. ltosol1(parens)
  402.     register char *parens;
  403. {
  404.     register char *cp;
  405.  
  406.     if (*parens && !*wcursor && !lnext())
  407.         return (0);
  408.     while (isspace(*wcursor) || (*wcursor == 0 && *parens))
  409.         if (!lnext())
  410.             return (0);
  411.     if (any(*wcursor, parens) || dir > 0)
  412.         return (1);
  413.     for (cp = wcursor; cp > linebuf; cp--)
  414.         if (isspace(cp[-1]) || any(cp[-1], parens))
  415.             break;
  416.     wcursor = cp;
  417.     return (1);
  418. }
  419.  
  420. lskipbal(parens)
  421.     register char *parens;
  422. {
  423.     register int level = dir;
  424.     register int c;
  425.  
  426.     do {
  427.         if (!lnext()) {
  428.             wdot = NOLINE;
  429.             return (0);
  430.         }
  431.         c = *wcursor;
  432.         if (c == parens[1])
  433.             level--;
  434.         else if (c == parens[0])
  435.             level++;
  436.     } while (level);
  437.     return (1);
  438. }
  439.  
  440. lskipatom()
  441. {
  442.  
  443.     return (lskipa1("()"));
  444. }
  445.  
  446. lskipa1(parens)
  447.     register char *parens;
  448. {
  449.     register int c;
  450.  
  451.     for (;;) {
  452.         if (dir < 0 && wcursor == linebuf) {
  453.             if (!lnext())
  454.                 return (0);
  455.             break;
  456.         }
  457.         c = *wcursor;
  458.         if (c && (isspace(c) || any(c, parens)))
  459.             break;
  460.         if (!lnext())
  461.             return (0);
  462.         if (dir > 0 && wcursor == linebuf)
  463.             break;
  464.     }
  465.     return (ltosol1(parens));
  466. }
  467.  
  468. lnext()
  469. {
  470.  
  471.     if (dir > 0) {
  472.         if (*wcursor)
  473.             wcursor++;
  474.         if (*wcursor)
  475.             return (1);
  476.         if (wdot >= llimit) {
  477.             if (lf == vmove && wcursor > linebuf)
  478.                 wcursor--;
  479.             return (0);
  480.         }
  481.         wdot++;
  482.         getline(*wdot);
  483.         wcursor = linebuf;
  484.         return (1);
  485.     } else {
  486.         --wcursor;
  487.         if (wcursor >= linebuf)
  488.             return (1);
  489. #ifdef LISPCODE
  490.         if (lf == lindent && linebuf[0] == '(')
  491.             llimit = wdot;
  492. #endif
  493.         if (wdot <= llimit) {
  494.             wcursor = linebuf;
  495.             return (0);
  496.         }
  497.         wdot--;
  498.         getline(*wdot);
  499.         wcursor = linebuf[0] == 0 ? linebuf : strend(linebuf) - 1;
  500.         return (1);
  501.     }
  502. }
  503.  
  504. lbrack(c, f)
  505.     register int c;
  506.     int (*f)();
  507. {
  508.     register line *addr;
  509.  
  510.     addr = dot;
  511.     for (;;) {
  512.         addr += dir;
  513.         if (addr < one || addr > dol) {
  514.             addr -= dir;
  515.             break;
  516.         }
  517.         getline(*addr);
  518.         if (linebuf[0] == '{' ||
  519. #ifdef LISPCODE
  520.             value(LISP) && linebuf[0] == '(' ||
  521. #endif
  522.             isa(svalue(SECTIONS))) {
  523.             if (c == ']' && f != vmove) {
  524.                 addr--;
  525.                 getline(*addr);
  526.             }
  527.             break;
  528.         }
  529.         if (c == ']' && f != vmove && linebuf[0] == '}')
  530.             break;
  531.     }
  532.     if (addr == dot)
  533.         return (0);
  534.     if (f != vmove)
  535.         wcursor = c == ']' ? strend(linebuf) : linebuf;
  536.     else
  537.         wcursor = 0;
  538.     wdot = addr;
  539.     vmoving = 0;
  540.     return (1);
  541. }
  542.  
  543. isa(cp)
  544.     register char *cp;
  545. {
  546.  
  547.     if (linebuf[0] != '.')
  548.         return (0);
  549.     for (; cp[0] && cp[1]; cp += 2)
  550.         if (linebuf[1] == cp[0]) {
  551.             if (linebuf[2] == cp[1])
  552.                 return (1);
  553.             if (linebuf[2] == 0 && cp[1] == ' ')
  554.                 return (1);
  555.         }
  556.     return (0);
  557. }
  558.